﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class Player : MonoBehaviour,IPointerEnterHandler,IPointerExitHandler
{
    public bool IsPlaying;
    public int PlayerID;
    public GameObject[] ShapeGameObjects;
    public Text ScoreText;

    private Camera mainCrma;
    private RaycastHit objhit;
    private Ray _ray;
    private int FirstNum;
    private int SecondNum;

    public Action StartRoundAction;
    public static Func<int[][,]> ProtoMode;
    public static Action FallDownAction; 
    private MapItem item;
    private int[,] Mode;
    private List<MapItem> CurrentMapItems;
    public static Action RotateShowAction;
    void Awake()
    {
        StartRoundAction += StartRound;
        FallDownAction += FallDown;
        RotateShowAction += RotateShowModel;
    }
    // Use this for initialization
    void Start () {
        CurrentMapItems = new List<MapItem>();
        mainCrma = Camera.main;
        FirstNum = 0;
        SecondNum = 1;

        for (int i = 0; i < 3; i++)
        {
            StartRound();
        }
    }
	
	// Update is called once per frame
	void Update () {
        if(!IsPlaying)
            return;
        if(PlayerID != GameManager.CurrentPlayer)
            return;
        if (Input.GetMouseButton(0))
        {
            _ray = mainCrma.ScreenPointToRay(Input.mousePosition);
            //Debug.DrawLine(_ray.origin, objhit.point, Color.red, 0.5f);

            if (Physics.Raycast(_ray, out objhit, 100))
            {
                item = objhit.collider.gameObject.GetComponent<MapItem>();
                if (item.X != GameState.CurrentX || item.Y != GameState.CurrentY)
                {
                    GameState.CurrentX = item.X;
                    GameState.CurrentY = item.Y;
                    ShowInMap();
                }
            }
        }

    }

    private void ShowInMap()
    {
        if(ProtoMode == null)
            return;

        CurrentMapItems.Clear();
        MapItem.ResetSelectedStateAction();

        Cards.IsCanFallDown = true;
        Mode = ProtoMode()[GameState.CurrentModeIndex];

        JudgeItemShowState();
    }

    private void RotateShowModel()
    {
        ShowInMap();
    }

    private void FallDown()
    {
        if (PlayerID != GameManager.CurrentPlayer)
            return;
        if (Cards.CurrntCardInHandGameObject != null)
        {
            Destroy(Cards.CurrntCardInHandGameObject);
            Cards.CurrntCardInHandGameObject = null;
        }
        else
        {
            Debug.LogError("CurrntCardInHandGameObject 为空");
        }
        
        foreach (MapItem mapItem in CurrentMapItems)
        {
            mapItem.State = MapItemState.Placed;
        }
        CurrentMapItems.Clear();
        FinishRowFun();
        ProtoMode -= ProtoMode;
    }

    private void FinishRowFun()
    {
        List<MapItem> finishList = new List<MapItem>();
        List <MapItem> temp = new List<MapItem>();
        for (int i = 0; i < CreatMap.m_width; i++)
        {
            for (int j = 0; j < CreatMap.m_heigth; j++)
            {
                //列
                if (CreatMap.MapItems[i, j].GetComponent<MapItem>().State == MapItemState.Placed)
                {
                    temp.Add(CreatMap.MapItems[i, j].GetComponent<MapItem>());
                }
                else
                {
                    temp.Clear();
                    break;
                }
            }

            if (temp.Count == CreatMap.m_heigth)
            {
                foreach (MapItem mapItem in temp)
                {
                    if (!finishList.Contains(mapItem))
                    {
                        finishList.Add(mapItem);
                    }
                }
            }
            temp.Clear();
        }

        for (int i = 0; i < CreatMap.m_width; i++)
        {
            for (int j = 0; j < CreatMap.m_heigth; j++)
            {
                //行
                if (CreatMap.MapItems[j, i].GetComponent<MapItem>().State == MapItemState.Placed)
                {
                    temp.Add(CreatMap.MapItems[j, i].GetComponent<MapItem>());
                }
                else
                {
                    temp.Clear();
                    break;
                }
            }

            if (temp.Count == CreatMap.m_heigth)
            {
                foreach (MapItem mapItem in temp)
                {
                    if (!finishList.Contains(mapItem))
                    {
                        finishList.Add(mapItem);
                    }
                }
                
            }
            temp.Clear();
        }

        foreach (MapItem mapItem in finishList)
        {
            mapItem.State = MapItemState.Free;
        }
        ScoreText.text = (int.Parse(ScoreText.text) + finishList.Count).ToString();

        finishList.Clear();
    }

    private void JudgeItemShowState()
    {
        for (int i = 0; i < Mode.Length / 2; i++)
        {
            if (!SetItemState(Mode[i, 0], Mode[i, 1]))
            {
                Cards.IsCanFallDown = false;
            }
        }

        if (Cards.IsCanFallDown == false)
        {
            MapItem item;
            for (int i = 0; i < Mode.Length/2; i++)
            {
                if (Mode[i, 0] >= 0 && Mode[i, 1] >= 0 && Mode[i, 0] < CreatMap.m_width && Mode[i, 1] < CreatMap.m_heigth)
                {
                    item = CreatMap.MapItems[Mode[i, 0], Mode[i, 1]].GetComponent<MapItem>();
                    item.SelectedState = MapItemSelectedState.InvalidSelected;
                }
            }
        }
    }

    private bool SetItemState(int x,int y)
    {
        MapItem item;
        try
        {
            item = CreatMap.MapItems[x, y].GetComponent<MapItem>();
        }
        catch (IndexOutOfRangeException)
        {
            foreach (MapItem mapItem in CurrentMapItems)
            {
                mapItem.SelectedState = MapItemSelectedState.InvalidSelected;
            }
            return false;
        }
       
        CurrentMapItems.Add(item);
        if (x >= 0 && y >= 0)
        {
            if (item.State == MapItemState.Placed)
            {
                item.SelectedState = MapItemSelectedState.InvalidSelected;
                return false;
            }
            else
            {
                item.SelectedState = MapItemSelectedState.ValidSelected;
                return true;
            }
        }
        else
        {
            item.SelectedState = MapItemSelectedState.InvalidSelected;
            return false;
        }
       
    }

    private void StartRound()
    {
        Instantiate(ShapeGameObjects[SpawnRandomIndex()], transform);
    }

    public void OnPointerEnter(PointerEventData eventData)
    {
        if (PlayerID != GameManager.CurrentPlayer)
            return;
        if (Cards.CurrntCardInHandGameObject != null)
        {
            Cards.CurrntCardInHandGameObject.SetActive(true);
            MapItem.ResetSelectedStateAction();
        }
    }

    public void OnPointerExit(PointerEventData eventData)
    {
        if (PlayerID != GameManager.CurrentPlayer)
            return;
        if (Cards.CurrntCardInHandGameObject != null)
        {
            Cards.CurrntCardInHandGameObject.SetActive(false);
        }
    }

    private int SpawnRandomIndex()
    {
        int random = UnityEngine.Random.Range(0, 7);

        while (FirstNum == SecondNum && SecondNum == random)
        {
            random = UnityEngine.Random.Range(0, 7);
        }

        FirstNum = SecondNum;
        SecondNum = random;
        return random;
    }
}
